from django.shortcuts import render,redirect
#导包
from django.http import HttpResponse,HttpResponseRedirect,JsonResponse
#导入类视图
from django.views import View

from myapp.models import User
import json
from django.core.serializers import serialize
from rest_framework.response import Response
from rest_framework.views import APIView
#导入加密库
import hashlib
#导入图片库
#绘画库
from PIL import ImageDraw
#字体库
from PIL import ImageFont
#图片库
from PIL import Image
#随机库
import random
#文件流
import io

import requests

#导入上传文件夹配置
from mydjango.settings import UPLOAD_ROOT
import os

#导入原生sql模块
from django.db import connection

import jwt

#导入redis数据库
import redis

#导入时间模块
import time

#导入公共目录变量
from mydjango.settings import BASE_DIR

#导包
from django.db.models import Q,F

#导入dwebsocket的库
from dwebsocket.decorators import accept_websocket
import uuid

# 导入序列化对象
from myapp.myser import UserSer

# 导包
import redis

# 定义ip地址和端口
host = '127.0.0.1'
port = 6379

# 定义链接对象
r = redis.Redis(host=host, port=port)

# 导包
from django.utils.deprecation import MiddlewareMixin

# 自定义中间件类
class MyMiddleWare(MiddlewareMixin):
    # 请求之前
    def process_request(self, request):
        # uid = request.GET.get('uid')
        # clinet_jwt = request.GET.get('jwt', None)

        # if clinet_jwt == None:
        #     return HttpResponse('你没有带上令牌')

        # print(uid)

        # decode_jwt = jwt.decode(clinet_jwt, 'xing', algorithms=['HS256'])

        # if decode_jwt['uid'] != str(uid):
        #     return HttpResponse('你篡改了用户id')
            
        pass

    # 模板渲染之前
    def process_view(self, request, view_func, view_args, view_kwargs):
        pass

    # 请求之后
    def process_response(self, request, response):
        return response

# 装饰器
def my_decorator(func):
    def wrapper(request, *args, **kwargs):
        # print('这个装饰器被调用了')
        # print('请求接口地址是%s' % request.path)

        # # 判断jwt逻辑
        # uid = request.GET.get('uid')
        # clinet_jwt = request.GET.get('jwt', None)

        # decode_jwt = jwt.decode(clinet_jwt, 'xing', algorithms=['HS256'])
        # if decode_jwt['uid'] != str(uid):
        #     return HttpResponse('你篡改了用户id')

        return func(request, *args, **kwargs)

    return wrapper

# 类装饰器调用
from django.utils.decorators import method_decorator

# 用户信息
class UserInfo(APIView):
    @method_decorator(my_decorator)
    def get(self, request):
        uid = request.GET.get('uid')
         # 查询数据
        user = User.objects.get(id=int(uid))

        # 序列化对象
        user_ser = UserSer(user)

        return Response(user_ser.data)


# 更新用户数据
class UpdateUser(APIView):
    def get(self, request):
        img = request.GET.get('img')
        uid = request.GET.get('uid')
        # 查询数据
        user = User.objects.get(id=int(uid))
        user.img = img
        user.save()

        res = {}
        res['code'] = 200
        res['message'] = '更新成功'
        return Response(res)

# 定义七牛云存储接口
from qiniu import Auth

class QiNiu(APIView):
    def get(self, request):
        # 定义密钥
        q = Auth('gne8IIvxIQPLlv5U6PoSHWi5RKbRWObzcfPU-zse', 'SePCg8HiTpN5_ugZ9uYhN0BxWWXzMWPC0KJ5GdcD')

        # 指定上传空间
        token = q.upload_token('tianshangxing')

        print(token)

        res = {}
        res['token'] = token

        return Response(res)


# 修改密码
class ChangePassword(APIView):
    def get(self, request):
        # 接受参数
        uid = request.GET.get('uid')
        password = request.GET.get('password')

        #查询
        user = User.objects.get(id=int(uid))

        # 判断修改的与之前是否一致
        if make_password(password) != user.password:
        
            # 修改保存
            user.password=make_password(password)
            user.save()
            res = {}
            res['code'] = 200
            res['message'] = '修改成功'
            return Response(res)
        else:
            res = {}
            res['code'] = 405
            res['message'] = '当前输入密码与原密码相同'
            return Response(res)


# 定义上传视图类
class UploadFile(View):
    def post(self, request):
        # 接收参数
        img = request.FILES.get('file')

        # 建立文件流对象
        f = open(os.path.join(UPLOAD_ROOT, '', img.name), 'wb')

        # 写入服务器端
        for chunk in img.chunks():
            f.write(chunk)
        f.close()

        # 打开图片
        im = Image.open(img)

        # 生成画笔对象
        draw = ImageDraw.Draw(im)

        # 设置字体
        my_font = ImageFont.truetype('c:\\Windows\\Fonts\\BAUHS93.TTF', size=50)

        # 修改图片
        draw.text((0, 0), 'Xing', font=my_font ,fill=(76, 234, 124, 180))

        # 定义存储路径
        storagepath='./static/upload/'+img.name

        im.save(storagepath)

        # 返回文件名
        return HttpResponse(json.dumps({'filename': img.name}, ensure_ascii=False), content_type='application/json')

# 定义钉钉回调
import hmac
import base64
from hashlib import sha256
import urllib

def ding_back(request):
    #获取code
    code = request.GET.get("code")

    t = time.time()

    # 时间戳
    timestamp = str((int(round(t * 1000))))
    appSecret ='fp3nkGoIhS2Mi9EdVql_nKXg6Y0-HSGp-2F_p7IAv_Quc56yhhrinpqbcQRg3RqF'

    # 构造签名
    signature = base64.b64encode(hmac.new(appSecret.encode('utf-8'),timestamp.encode('utf-8'), digestmod=sha256).digest())

    # 请求接口，换取钉钉用户名
    payload = {'tmp_auth_code':code}
    headers = {'Content-Type': 'application/json'}
    res = requests.post('https://oapi.dingtalk.com/sns/getuserinfo_bycode?signature='+urllib.parse.quote(signature.decode("utf-8"))+"&timestamp="+timestamp+"&accessKey=dingoahmelrgy51wltnjzs",data=json.dumps(payload),headers=headers)

    res_dict = json.loads(res.text)
    print(res_dict)
    # return HttpResponse(res.text)

    # 判断是否为第一次钉钉登录
    user = User.objects.filter(username=str(res_dict['user_info']['nick'])).first()

    ding_id = ''
    user_id = ''

    if user:
        # 代表曾经用过钉钉登录
        ding_id = user.username
        user_id = user.id

    else:
        # 代表首次登录，入库
        user = User(username=str(res_dict['user_info']['nick']), password='')
        # 保存入库
        user.save()
        
        # 查询用户id
        user = User.objects.filter(username=str(res_dict['user_info']['nick'])).first()
        ding_id = str(res_dict['user_info']['nick'])
        user_id = user.id
    # 进行跳转
    return redirect('http://localhost:8080?ding_id=' + str(ding_id) + '&uid=' + str(user_id))

# 新浪微博回调
def web_back(request):
    # 获取code
    code = request.GET.get('code')
    # 定义微博认证地址
    access_token_url = 'https://api.weibo.com/oauth2/access_token'

    # 参数
    res = requests.post(
        access_token_url,
        data={
            'client_id': '470406121',
            'client_secret': 'a38003908bced9033a913ea8ac878980',
            'grant_type': 'authorization_code',
            'code': code,
            'redirect_uri': 'http://127.0.0.1:8000/md_admin/weibo'
        }
    )

    # 转换类型
    res = json.loads(res.text)
    # res = eval(res.text)

    # 获取微博昵称
    result = requests.get('https://api.weibo.com/2/users/show.json', params={'access_token': res['access_token'], 'uid': res['uid']})

    # print(result.text)

    result = json.loads(result.text)

    
    # 判断是否为第一次新浪登录
    user = User.objects.filter(username=str(result['name'])).first()

    sina_id = ''
    user_id = ''

    if user:
        # 代表曾经用过新浪登录
        sina_id = user.username
        user_id = user.id

    else:
        # 代表首次登录，入库
        user = User(username=str(result['name']), password='')
        # 保存入库
        user.save()
        
        # 查询用户id
        user = User.objects.filter(username=str(result['name'])).first()
        sina_id = str(result['name'])
        user_id = user.id   

    # 进行跳转
    return redirect('http://localhost:8080?sina_id=' + str(sina_id) + '&uid=' + str(user_id))

# 定义验证码类 APIView 返回json
class MyCode(View):
    # 定义随机颜色
    def get_random_color(self):
        R = random.randrange(255)
        G = random.randrange(255)
        B = random.randrange(255)
        return (R, G, B)
    
    # 获取验证码视图
    def get(self, request):
        # 画布
        img_size = (130, 50)
        # 定义画图对象
        image = Image.new('RGB', img_size, '#FFFFE0')
        # 定义画笔对象
        draw = ImageDraw.Draw(image, 'RGB')
        # 定义随机字符串
        source = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
        # source = '中国武汉加油挺住必胜'
        # 定义容器
        code_str = ''
        # 定义字体
        my_font = ImageFont.truetype(font="c:\\Windows\\Fonts\\comic.ttf", size=25)
        # my_font = ImageFont.truetype(font="c:\\Windows\\Fonts\\STXINGKA.TTF", size=25)
        
        for i in range(4):
            # 获取随机颜色
            text_color = self.get_random_color()
            # 获取随机字符串长度下标
            tmp_num = random.randrange(len(source))
            # 获取字符集
            random_str = source[tmp_num]
            # 添加到容器中
            code_str += random_str
            # 将字符串添加到画布
            draw.text((10+30*i, 10), random_str, text_color, font=my_font)
        # 建立缓存区
        buf = io.BytesIO()
        # 将验证码存储到redis中
        r.set('code', code_str)
        # 保存图片
        image.save(buf, 'png')

        # 存储到session
        request.session['code'] = code_str

        return HttpResponse(buf.getvalue(), 'image/png')


# md5加密方法
def make_password(mypass):
    # 生成md5对象
    md5 = hashlib.md5()
    # 定义机密对象
    sign_str = str(mypass)
    # 转码
    sign_utf8 = sign_str.encode(encoding='utf-8')
    # 加密
    md5.update(sign_utf8)
    # 生成密码串
    md5_server = md5.hexdigest()

    return md5_server

# 登录接口
class Login(APIView):
    def get(self, request):
        # 接收参数
        username = request.GET.get('username', '')
        password = request.GET.get('password', '')

        # 查询数据
        user = User.objects.filter(username=username, password=make_password(password)).first()

        if user:
            res = {}
            res['code'] = 200
            res['message'] = '登录成功'
            res['username'] = user.username
            res['uid'] = user.id
            # 加入jwt令牌机制
            # 进行编码
            encode_jwt = jwt.encode({'uid': str(user.id)}, 'xing', algorithm='HS256')
            # 解码操作
            # 强转
            encode_str = str(encode_jwt, 'utf-8')
            res['jwt'] = encode_str
            return Response(res)

        else:
            res = {}
            res['code'] = 405
            res['message'] = '用户名或密码错误'
            return Response(res)

# 注册模块
class Register(APIView):
    def get(self, request):
        # 接收参数
        username = request.GET.get('username', '')
        password = request.GET.get('password', '')
        code = request.GET.get('code', '')

        # 获取验证码
        redis_code = r.get('code')
        # 转码
        redis_code = redis_code.decode('utf-8')

        # 获取session中的验证码
        session_code = request.session.get('code') 

        print(code)
        print(redis_code)
        print('session: %s' % str(session_code))

        # 判断验证码是否正确
        if code != redis_code:
            res = {}
            res['code'] = 405
            res['message'] = '验证码输入错误'
            return Response(res)

        # 排重
        user = User.objects.filter(username=username).first()

        if user:
            res = {}
            res['code'] = 405
            res['message'] = '该用户名已存在'
            return Response(res)

        # 入库
        user = User(username=username, password=make_password(password))
        user.save()

        res = {}
        res['code'] = 200
        res['message'] = '注册成功'
        return Response(res)
